﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LocalServerApp;

namespace Client
{
    public class KortService : subject
    {
        private List<Observer> observers = new List<Observer>();
        private List<KortType> kortList = new List<KortType>();
        private StringBuilder currentInput = new StringBuilder();
        private KortType currentCard;
        private Boolean isReading = false;
        Person p = null;
        
        
        public KortService()
        {
            setupCards();
        }

        /// <summary>
        /// Denne metode bruges til at lave en instans af de forskellige kort.
        /// setupCards er det eneste sted i koden man behøver at ændre, 
        /// for at korttypen bliver medtaget i genkendelse processen.
        /// </summary>    
        public void setupCards()
        {
            NordeaVisaDankort nordeaVisaDankort = new NordeaVisaDankort();
            Sygesikring sygesikring = new Sygesikring();
            FejlGeneral fejlGeneral = new FejlGeneral();
            FejlGennemførsel fejlGennemførsel = new FejlGennemførsel();
            FejlSkråGennemførsel fejlSkråGennemførsel = new FejlSkråGennemførsel();
            FejlFire fejlFire = new FejlFire();

            kortList.Add(fejlFire);
            kortList.Add(fejlSkråGennemførsel);
            kortList.Add(fejlGennemførsel);
            kortList.Add(fejlGeneral);
            kortList.Add(nordeaVisaDankort);
            kortList.Add(sygesikring); 
        }


        /// <summary>
        /// Metoden modtager inputs fra tastatur og kortlæser, fra en previewtextlistener
        /// på mainwindow. input bliver kun gemt hvis det indkommene tegn kommer i mellem 
        /// '%' og '\r'. Hvis det indkommene tegn er '\r' bliver dataen forsøgt
        /// genkendt.
        /// </summary>
        /// <param name="cardInput"></param>
        public void cardReaderInput(String cardInput)
       {
            validateReading(cardInput);

            if (isReading == true)
            {
                currentInput.Append(cardInput);

                if (cardInput.Equals("\r"))
                {
                    recogniseCardType(cardInput);
                }
            }
        }

        /// <summary>
        /// Metoden sætter isReading til true eller false, og på den måde
        /// åbner og lukker for indscanning af kort data. Hvis metoden modtager et '%'
        /// bliver isReading sat til true, da dette er start tegnet på et kort.
        /// </summary>
        /// <param name="cardInput"></param>
        public void validateReading(string cardInput)
             {
            if (cardInput.Equals("%"))
            { isReading = true; }
        }

        /// <summary>
        /// Metoden forsøger at finde det kort der matcher det indkommene data. findes
        /// ingen kort er dette fordi det indscannet kort ikke understøttes af systemet,
        /// og alt genkendelseslogik bliver nulstillet og er igen klart til modtagelse.
        /// </summary>
        public void recogniseCardType(string cardInput)
           {
                   foreach (KortType k in kortList)
                    {
                        if (k.recogniseCardType(currentInput.ToString()) == true)
                        {
                            currentCard = k;
                            setPersonFromCardString(currentInput.ToString(), k);                            
                            break;
                        }
                   }
                   clearAllInput();
            }


        public string getCurrentInput()
        { return currentInput.ToString(); }


        public string getCurrentCardName()
        {
            if (currentCard == null) 
            { return "Ukendt Kort";}
            else
            {return currentCard.getCardName();}
        }

        private void setPersonFromCardString(String cardString, KortType k)
        {
            p = k.getCardInfo(cardString);
            Notify();
            clearAllInput();
        }


        #region subject Members

        public void RegObserver(Observer o)
        {
            observers.Add(o);
        }

        public void RemObserver(Observer o)
        {
            observers.Remove(o);
        }

        public void Notify()
        {
            foreach (Observer o in observers)
            {
                o.updateNewPerson(p);
                clearAllInput();
            }
        }

        #endregion

        public void clearAllInput()
        {
            p = null;
            currentInput.Clear();
            currentCard = null;
            isReading = false;
        }
    }
}
